#include "BodyFileFormat.h"
#include "Common/Geometry/Polygon.h"

using namespace cmn;

BodyEntity* BodyFileFormat::Load( const std::string& filename ) {
	return LoadFromDto( data::LoadBody( filename ) );
}

void BodyFileFormat::Save( const BodyEntity* bodyEntity, const std::string& filename ) {
	data::SaveBody( SaveToDto( bodyEntity ), filename );
}

BodyEntity* BodyFileFormat::LoadFromDto( const data::Body& dataBody ) {
	BodyEntity* bodyEntity =
		new BodyEntity(
		dataBody.GetMass(),
		dataBody.GetInertia(),
		dataBody.GetFriction(),
		dataBody.GetRestitution() );

	for( IteratorPtr<data::PolygonShape> dataPolygons( dataBody.GetPolygons() );
			!dataPolygons.IsEnd();
			dataPolygons.Next() )
	{
		const data::PolygonShape dataPolygon = dataPolygons.Current();
		Transform polygonPos = dataPolygon.GetPosition();

		PolygonEntity* polygonEntity = new PolygonEntity( bodyEntity, polygonPos );
		bodyEntity->AddPolygon( polygonEntity );

		Polygon polygon = dataPolygon.GetPolygon();

		for( int i = 0; i < polygon.GetVerticesCount(); ++i ) {
			VertexEntity* vertexEntity = new VertexEntity( polygonEntity, polygon[i] );
			polygonEntity->AddVertex( vertexEntity );
		}
	}

	for( IteratorPtr<Circle> dataCircles( dataBody.GetCircles() );
			!dataCircles.IsEnd();
			dataCircles.Next() )
	{
		const Circle circle = dataCircles.Current();

		CircleEntity* circleEntity = new CircleEntity( bodyEntity, circle );
		bodyEntity->AddCircle( circleEntity );
	}

	return bodyEntity;
}

data::Body BodyFileFormat::SaveToDto( const BodyEntity* bodyEntity ) const {
	data::Body dataBody(
		bodyEntity->GetMass(),
		bodyEntity->GetInertia(),
		bodyEntity->GetFriction(),
		bodyEntity->GetRestitution() );

	Vector<CircleEntity*> circles;
	bodyEntity->GetCircles( circles );
	for( IteratorPtr<CircleEntity*> circlesIter( circles );
			!circlesIter.IsEnd();
			circlesIter.Next() )
	{
		const CircleEntity* circleEntity = circlesIter.Current();
		dataBody.AddCircle( circleEntity->GetCircle() );
	}

	Vector<PolygonEntity*> polygons;
	bodyEntity->GetPolygons( polygons );
	for( IteratorPtr<PolygonEntity*> polygonsIter( polygons );
			!polygonsIter.IsEnd();
			polygonsIter.Next() )
	{
		const PolygonEntity* polygonEntity = polygonsIter.Current();

		Polygon polygon;
		Vector<VertexEntity*> vertices;
		polygonEntity->GetVertices( vertices );
		for( IteratorPtr<VertexEntity*> verticesIter( vertices );
				!verticesIter.IsEnd();
				verticesIter.Next() )
		{
			const VertexEntity* vertexEntity = verticesIter.Current();
			polygon.AddVertex( vertexEntity->GetPosition() );
		}

		data::PolygonShape dataPolygon( polygonEntity->GetPosition(), polygon );
		dataBody.AddPolygon( dataPolygon );
	}
	return dataBody;
}
